home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / comm / wnos5src.zip / NR4.C < prev    next >
Text File  |  1993-08-09  |  21KB  |  731 lines

  1. /* net/rom level 4 (transport) protocol implementation
  2.  * Copyright 1989 by Daniel M. Frank, W9NK.  Permission granted for
  3.  * non-commercial distribution only.
  4.  * Ported to NOS by SM0RGV, 890525.
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include "global.h"
  9. #include "config.h"
  10. #ifdef NETROM
  11. #include "mbuf.h"
  12. #include "timer.h"
  13. #include "ax25.h"
  14. #include "netrom.h"
  15. #include "nr4.h"
  16. #include <ctype.h>
  17.  
  18. #undef NR4DEBUG
  19.  
  20. /* Globals: */
  21.  
  22. /* The circuit table */
  23. struct nr4circp Nr4circuits[NR4MAXCIRC];
  24.  
  25. /* Various limits */
  26. unsigned short Nr4window     = 4;        /* Max window to negotiate */
  27. unsigned short Nr4retries     = 3;        /* Max retries */
  28. unsigned short Nr4qlimit     = 2048;        /* Max bytes on receive queue */
  29.  
  30. /* Timers */
  31. int16 Nr4irtt               = 60;       /* Initial round trip time */
  32. int16 Nr4acktime             = 3;        /* ACK delay timer */
  33. int16 Nr4choketime             = 180;        /* CHOKEd state timeout */
  34.  
  35. static void near nr4ackours __ARGS((struct nr4cb *, unsigned, int));
  36. static void near nr4choke __ARGS((struct nr4cb *));
  37. static void near nr4gotnak __ARGS((struct nr4cb *, unsigned));
  38. static void near nr4rframe __ARGS((struct nr4cb *, unsigned, struct mbuf *));
  39.  
  40. /* This function is called when a net/rom layer four frame */
  41. /* is discovered inside a datagram addressed to us */
  42. void
  43. nr4input(hdr,bp)
  44. struct nr4hdr *hdr;
  45. struct mbuf *bp;
  46. {
  47.     struct nr4hdr rhdr;
  48.     struct nr4cb *cb, *cb2;
  49.     int gotchoke;        /* The choke flag was set in this packet */
  50.     unsigned window;
  51.     int i;
  52.  
  53.     int op = hdr->opcode & NR4OPCODE;    /* Mask off flags */
  54.  
  55.     if(op == NR4OPCONRQ){            /* process connect request first */
  56.         int acceptc = 1;    /* indicates that connection should be accepted */
  57.         int newconn = 0;    /* indicates that this is a new incoming */
  58.                             /* connection.  You'll see. */
  59.  
  60.         /* These fields are sent regardless of success */
  61.         rhdr.yourindex = hdr->u.conreq.myindex;
  62.         rhdr.yourid = hdr->u.conreq.myid;
  63.  
  64.         /* Check to see if we have already received a connect */
  65.         /* request for this circuit. */
  66.         if((cb = match_n4circ(hdr->u.conreq.myindex,
  67.           hdr->u.conreq.myid,hdr->u.conreq.user,hdr->u.conreq.node))
  68.           == NULLNR4CB) {    /* No existing circuit if NULL */
  69.  
  70.             /* Try to get a new circuit */
  71.             if((cb = new_n4circ()) == NULLNR4CB)
  72.                 acceptc = 0;
  73.             /* See if we have any listening sockets */
  74.             for(i = 0; i < NR4MAXCIRC; i++){
  75.                 if((cb2 = Nr4circuits[i].ccb) == NULLNR4CB)
  76.                 continue;/* not an open circuit */
  77.                 if(cb2->state == NR4STLISTEN)
  78.                     /* A listener was found */
  79.                     break;
  80.             }
  81.             if(i == NR4MAXCIRC){ /* We are refusing connects */
  82.                 acceptc = 0;
  83.                 free_n4circ(cb);
  84.             }
  85.             if(acceptc){
  86.                 /* Load the listeners settings */
  87.                 cb->clone = cb2->clone;
  88.                 cb->user = cb2->user;
  89.                 cb->t_upcall = cb2->t_upcall;
  90.                 cb->s_upcall = cb2->s_upcall;
  91.                 cb->r_upcall = cb2->r_upcall;
  92.                 ASSIGN(cb->local,cb2->local);
  93.  
  94.                 /* Window is set to min of the offered
  95.                  * and local windows
  96.                  */
  97.                 window = (unsigned)min(hdr->u.conreq.window,Nr4window);
  98.  
  99.                 if(init_nr4window(cb, window) == -1){
  100.                     free_n4circ(cb);
  101.                     acceptc = 0;
  102.                 } else {
  103.                     /* Set up control block */
  104.                     cb->yournum = hdr->u.conreq.myindex;
  105.                     cb->yourid = hdr->u.conreq.myid;
  106.                     memcpy(cb->remote.user,
  107.                            hdr->u.conreq.user,AXALEN);
  108.                     memcpy(cb->remote.node,
  109.                            hdr->u.conreq.node,AXALEN);
  110.                     /* Default round trip time */
  111.                     cb->srtt = Nr4irtt * 1000;
  112.                     /* set up timers, window pointers */
  113.                     nr4defaults(cb);
  114.                     cb->state = NR4STDISC;
  115.                     newconn = 1;
  116.                 } /* End if window successfully allocated */
  117.             }    /* End if new circuit available */
  118.          } /* End if no existing circuit matching parameters */
  119.  
  120.         /* Now set up response */
  121.         if(!acceptc){
  122.             rhdr.opcode = NR4OPCONAK | NR4CHOKE;/* choke means reject */
  123.             rhdr.u.conack.myindex = 0;
  124.             rhdr.u.conack.myid = 0;
  125.             rhdr.u.conack.window = 0;
  126.         } else {
  127.             rhdr.opcode = NR4OPCONAK;
  128.             rhdr.u.conack.myindex = cb->mynum;
  129.             rhdr.u.conack.myid = cb->myid;
  130.             rhdr.u.conack.window = cb->window;
  131.         }
  132.         nr4sframe(hdr->u.conreq.node, &rhdr, NULLBUF);
  133.  
  134.         /* Why, you ask, do we wait until now for the state change
  135.          * upcall?  Well, it's like this:  if the state change triggers
  136.          * something like the mailbox to send its banner, the banner
  137.          * would have gone out *before* the conn ack if we'd done this
  138.          * in the code above.  This is what happens when you don't plan
  139.          * too well.  Learn from my mistakes :-)
  140.          */
  141.         if(newconn) {
  142.             nr4state(cb, NR4STCON);        /* connected (no 3-way handshake) */
  143.             start_timer(&cb->inactivity);
  144.         }
  145.         free_p(bp);
  146.         return;
  147.     } /* end connect request code */
  148.  
  149.     /* validate circuit number */
  150.     if((cb = get_n4circ(hdr->yourindex, hdr->yourid)) == NULLNR4CB){
  151.         free_p(bp);
  152.         return;
  153.     }
  154.  
  155.     /* Check for choke flag */
  156.     gotchoke = (hdr->opcode & NR4CHOKE) ? 1 : 0;
  157.  
  158.     /* Here's where the interesting stuff gets done */
  159.     switch(cb->state){
  160.     case NR4STCPEND:
  161.         switch(op){
  162.         case NR4OPCONAK:
  163.             /* Save the round trip time for later use */
  164.             i = (int)(dur_timer(&cb->tcd) - read_timer(&cb->tcd));
  165.             stop_timer(&cb->tcd);
  166.             if(gotchoke){        /* connect rejected */
  167.                 cb->dreason = NR4RREFUSED;
  168.                 nr4state(cb, NR4STDISC);
  169.                 break;
  170.             }
  171.             cb->yournum = hdr->u.conack.myindex;
  172.             cb->yourid = hdr->u.conack.myid;
  173.             window = (unsigned)min(hdr->u.conack.window,Nr4window);
  174.  
  175.             if(init_nr4window(cb, window) == -1){
  176.                 reset_nr4(cb);
  177.             } else {
  178.                 nr4defaults(cb);    /* set up timers, window pointers */
  179.                 cb->srtt = (cb->cdtries == 1)
  180.                   ? (i * MSPTICK + MSPTICK) : (Nr4irtt * 1000);
  181.                 nr4state(cb, NR4STCON);
  182.                 nr4output(cb);        /* start sending anything on the txq */
  183.             }
  184.             break;
  185.         default:
  186.             /* We can't respond to anything else without
  187.              * Their ID and index
  188.              */
  189.             free_p(bp);
  190.             return;
  191.         }
  192.         break;
  193.     case NR4STCON:
  194.         switch(op){
  195.         case NR4OPDISRQ:
  196.             /* format reply packet */
  197.             rhdr.opcode = NR4OPDISAK;
  198.             rhdr.yourindex = cb->yournum;
  199.             rhdr.yourid = cb->yourid;
  200.             nr4sframe(cb->remote.node,&rhdr,NULLBUF);
  201.             cb->dreason = NR4RREMOTE;
  202.             nr4state(cb, NR4STDISC);
  203.             break;
  204.         case NR4OPINFO:
  205.             /* Do receive frame processing */
  206.               nr4rframe(cb, hdr->u.info.txseq, bp);
  207.  
  208.             /* Reset the choke flag if no longer choked.  Processing
  209.              * the ACK will kick things off again.
  210.              */
  211.             if(cb->choked && !gotchoke){
  212.                 stop_timer(&cb->tchoke);
  213.                 cb->choked = 0;
  214.             }
  215.  
  216.             /* We delay processing the receive sequence number until
  217.              * now, because the ACK might pull more off the txq and send
  218.              * it, and we want the implied ACK in those frames to be right
  219.              *
  220.              * Only process NAKs if the choke flag is off.  It appears
  221.              * that NAKs should never be sent with choke on, by the way,
  222.              * but you never know, considering that there is no official
  223.              * standard for this protocol
  224.              */
  225.             if(hdr->opcode & NR4NAK && !gotchoke)
  226.                 nr4gotnak(cb, hdr->u.info.rxseq);
  227.  
  228.             /* We always do ACK processing, too, since the NAK of one
  229.              * packet may be the implied ACK of another.  The gotchoke
  230.              * flag is used to prevent sending any new frames, since
  231.              * we are just going to purge them next anyway if this is
  232.              * the first time we've seen the choke flag.  If we are
  233.              * already choked, this call will return immediately.
  234.              */
  235.             nr4ackours(cb, hdr->u.info.rxseq, gotchoke);
  236.  
  237.             /* If we haven't seen the choke flag before, purge the
  238.              * send window and set the timer and the flag.
  239.              */
  240.             if(!cb->choked && gotchoke)
  241.                 nr4choke(cb);
  242.  
  243.             start_timer(&cb->inactivity);
  244.  
  245.             break;
  246.         case NR4OPACK:
  247.             if(cb->choked && !gotchoke){
  248.                 /* clear choke if appropriate */
  249.                 stop_timer(&cb->tchoke);
  250.                 cb->choked = 0;
  251.             }
  252.               if(hdr->opcode & NR4NAK && !gotchoke)
  253.                 nr4gotnak(cb, hdr->u.ack.rxseq);    /* process NAKs */
  254.  
  255.               nr4ackours(cb, hdr->u.ack.rxseq, gotchoke); /* and ACKs */
  256.  
  257.             if(!cb->choked && gotchoke)    /* First choke seen */
  258.                 nr4choke(cb);        /* Set choke status */
  259.  
  260.             break;
  261.         }
  262.         break;
  263.     case NR4STDPEND:
  264.         switch(op){
  265.         case NR4OPDISAK:
  266.               cb->dreason = NR4RNORMAL;
  267.             nr4state(cb, NR4STDISC);
  268.             break;
  269.         case NR4OPINFO:
  270.             /* We can still do receive frame processing until
  271.              * the disconnect acknowledge arrives, but we won't
  272.              * bother to process ACKs, since we've flushed our
  273.              * transmit buffers and queue already.
  274.              */
  275.               nr4rframe(cb, hdr->u.info.txseq, bp);
  276.             break;
  277.         }
  278.     }    /* End switch(state) */
  279. }
  280.  
  281.  
  282. /* Send a net/rom layer 4 frame.  bp should be NULLBUF unless the frame
  283.  * type is info.
  284.  */
  285. void
  286. nr4sframe(dest, hdr, bp)
  287. char *dest;
  288. struct nr4hdr *hdr;
  289. struct mbuf *bp;
  290. {
  291.     struct mbuf *n4b;
  292.  
  293.     if((n4b = htonnr4(hdr)) == NULLBUF){
  294.         free_p(bp);
  295.     } else {
  296.         append(&n4b, bp);
  297.         nr3output(dest, n4b);
  298.     }
  299. }
  300.  
  301. /* Receive frame processing */
  302. static void near
  303. nr4rframe(cb, rxseq, bp)
  304. struct nr4cb *cb;
  305. unsigned rxseq;
  306. struct mbuf *bp;
  307. {
  308.     unsigned window = cb->window;
  309.     unsigned rxbuf = rxseq % window;
  310.     unsigned newdata = 0;        /* whether to upcall */
  311.  
  312. #ifdef NR4DEBUG
  313.     tputs("Processing received info\n");
  314. #endif
  315.  
  316.     /* If we're choked, just reset the ACK timer to blast out
  317.      * another CHOKE indication after the ackdelay
  318.      */
  319.     if(cb->qfull){
  320.         start_timer(&cb->tack);
  321.         return;
  322.     }
  323.  
  324.     /* If frame is out of sequence, it is either due to a lost frame
  325.      * or a retransmission of one seen earlier.  We do not want to NAK
  326.      * the latter, as the far end would see this as a requirement to
  327.      * retransmit the expected frame, which is probably already in the
  328.      * pipeline.  This in turn would cause another out-of-sequence
  329.      * condition, another NAK, and the process would repeat indefinitely.
  330.      * Therefore, if the frame is out-of-sequence, but within the last
  331.      * 'n' frames by sequence number ('n' being the window size), just
  332.      * accept it and discard it.  Else, NAK it if we haven't already.
  333.      *    (Modified by Rob Stampfli, kd8wk, 9 Jan 1990)
  334.      */
  335.     if(rxseq != cb->rxpected && !cb->naksent){
  336.         struct nr4hdr rhdr;
  337.  
  338. #ifdef NR4DEBUG
  339.         tprintf("Frame out of sequence -- expected %u, got %u.\n",
  340.                cb->rxpected, rxseq);
  341. #endif
  342.         if(nr4between(cb->rxpected,
  343.            (rxseq + window) & NR4SEQMASK, cb->rxpastwin))
  344.             /* just a repeat of old frame -- queue ack for
  345.              * expected frame
  346.              */
  347.             start_timer(&cb->tack);
  348.         else {            /* really bogus -- a NAKable frame */
  349.             rhdr.opcode = NR4OPACK | NR4NAK;
  350.             rhdr.yourindex = cb->yournum;
  351.             rhdr.yourid = cb->yourid;
  352.             rhdr.u.ack.rxseq = cb->rxpected;
  353.             nr4sframe(cb->remote.node,&rhdr,NULLBUF);
  354.  
  355.             /* Now make sure we don't send any more of these until
  356.              * we see some good data.  Otherwise full window
  357.              * retransmissions would result in a flurry of NAKs
  358.              */
  359.  
  360.             cb->naksent = 1;
  361.         }
  362.     }
  363.  
  364.     /* If this is a new frame, within the window, buffer it,
  365.      * then see what we can deliver
  366.      */
  367.     if(nr4between(cb->rxpected,rxseq,cb->rxpastwin)
  368.         && !cb->rxbufs[rxbuf].occupied){
  369. #ifdef NR4DEBUG
  370.         tputs("Frame within window\n");
  371. #endif
  372.         cb->rxbufs[rxbuf].occupied = 1;
  373.         cb->rxbufs[rxbuf].data = bp;
  374.  
  375.         for(rxbuf = cb->rxpected % window; cb->rxbufs[rxbuf].occupied;
  376.              rxbuf = cb->rxpected % window){
  377. #ifdef NR4DEBUG
  378.             tprintf("Removing frame from buffer %d\n", rxbuf);
  379. #endif
  380.             newdata = 1;
  381.             cb->rxbufs[rxbuf].occupied = 0;
  382.             append(&cb->rxq,cb->rxbufs[rxbuf].data);
  383.             cb->rxbufs[rxbuf].data = NULLBUF;
  384.             cb->rxpected = (cb->rxpected + 1) & NR4SEQMASK;
  385.             cb->rxpastwin = (cb->rxpastwin + 1) & NR4SEQMASK;
  386.         }
  387.         if(newdata){
  388.             cb->naksent = 0;    /* OK to send NAKs again */
  389.             if(cb->r_upcall != NULLVFP)
  390.                 (*cb->r_upcall)(cb,len_p(cb->rxq));
  391.  
  392.             /* Now that our upcall has had a shot at the queue, */
  393.             /* see if it's past the queue length limit.  If so, */
  394.             /* go into choked mode (i.e. flow controlled). */
  395.  
  396.             if(len_p(cb->rxq) > Nr4qlimit){
  397.                 cb->qfull = 1;
  398.                 nr4ackit((void *)cb);    /* Tell `em right away */
  399.             } else
  400.                 start_timer(&cb->tack);
  401.         }
  402.     }  else     /* It's out of the window or we've seen it already */
  403.         free_p(bp);
  404. }
  405.  
  406.  
  407. /* Send the transmit buffer whose sequence number is seq */
  408. void
  409. nr4sbuf(cb, seq)
  410. struct nr4cb *cb;
  411. unsigned seq;
  412. {
  413.     struct nr4hdr hdr;
  414.     struct mbuf *bufbp, *bp;
  415.     struct timer *t;
  416.     unsigned bufnum = seq % cb->window;
  417.  
  418.     /* sanity check */
  419.     if(bufnum >= cb->window){
  420. #ifdef NRDEBUG
  421.         tprintf("sbuf: buffer number %u beyond window\n",bufnum);
  422. #endif
  423.         return;
  424.     }
  425.  
  426.     /* Stop the ACK timer, since our sending of the frame is
  427.      * an implied ACK.
  428.      */
  429.     stop_timer(&cb->tack);
  430.  
  431.     /* Duplicate the mbuf, since we have to keep it around
  432.      * until it is acknowledged
  433.      */
  434.     bufbp = cb->txbufs[bufnum].data;
  435.  
  436.     /* Notice that we use copy_p instead of dup_p.  This is because
  437.      * a frame can still be sitting on the AX.25 send queue when it
  438.      * get acknowledged, and we don't want to deallocate its data
  439.      * before it gets sent!
  440.      */
  441.     if((bp = copy_p(bufbp, len_p(bufbp))) == NULLBUF){
  442.         free_mbuf(bp);
  443.         return;
  444.     }
  445.  
  446.     /* Prepare the header */
  447.     hdr.opcode = (cb->qfull) ? (NR4OPINFO | NR4CHOKE) : NR4OPINFO;
  448.     hdr.yourindex = cb->yournum;
  449.     hdr.yourid = cb->yourid;
  450.     hdr.u.info.txseq = (unsigned char)(seq & NR4SEQMASK);
  451.     hdr.u.info.rxseq = cb->rxpected;
  452.  
  453.     /* Send the frame, then set and start the timer */
  454.     nr4sframe(cb->remote.node, &hdr, bp);
  455.  
  456.     t = &cb->txbufs[bufnum].tretry;
  457.     t->func = nr4txtimeout;
  458.     t->arg = cb;
  459.     set_timer(t, (1 << cb->blevel) * (4 * cb->mdev + cb->srtt) + MSPTICK);
  460.     start_timer(t);
  461.  
  462.     start_timer(&cb->inactivity);    /* restart l4 inactivity timer */
  463. }
  464.  
  465. /* Check to see if any of our frames have been ACKed */
  466.  
  467. static void near
  468. nr4ackours(cb, seq, gotchoke)
  469. struct nr4cb *cb;
  470. unsigned seq;
  471. int gotchoke;    /* The choke flag is set in the received frame */
  472. {
  473.     unsigned txbuf;
  474.  
  475.     /* If we are choked, there is nothing in the send window
  476.      * by definition, so we can just return.
  477.      */
  478.     if(cb->choked)
  479.         return;
  480.  
  481.     /* Adjust seq to point to the frame being ACK'd, not the one
  482.      * beyond it, which is how it arrives.
  483.      */
  484.     seq = (seq - 1) & NR4SEQMASK;
  485.  
  486.     /* Free up all the ack'd frames, and adjust the round trip
  487.      * timing stuff
  488.      */
  489.     while (nr4between(cb->ackxpected, seq, cb->nextosend)){
  490. #ifdef NR4DEBUG
  491.         tprintf("Sequence # %u acknowledged\n", seq);
  492. #endif
  493.         cb->nbuffered--;
  494.         txbuf = cb->ackxpected % cb->window;
  495.         free_mbuf(cb->txbufs[txbuf].data);
  496.         cb->txbufs[txbuf].data = NULLBUF;
  497.         cb->ackxpected = (cb->ackxpected + 1) & NR4SEQMASK;
  498.  
  499.         /* Round trip time estimation, cribbed from TCP */
  500.         if(cb->txbufs[txbuf].retries == 0){
  501.             /* We only sent this one once */
  502.             struct timer *t = &cb->txbufs[txbuf].tretry;
  503.  
  504.             /* get our rtt in msec */
  505.             int32 rtt = dur_timer(t) - read_timer(t);
  506.             int32 abserr = (rtt > cb->srtt) ? (rtt - cb->srtt) : (cb->srtt - rtt);
  507.  
  508.             cb->srtt = (cb->srtt * 7 + rtt) >> 3;
  509.             cb->mdev = (cb->mdev * 3 + abserr) >> 2;
  510.  
  511.             /* Reset the backoff level */
  512.             cb->blevel = 0;
  513.         }
  514.         stop_timer(&cb->txbufs[txbuf].tretry);
  515.     }
  516.     /* Now we recalculate tmax, the maximum number of retries for
  517.      * any frame in the window.  tmax is used as a baseline to
  518.      * determine when the window has reached a new high in retries.
  519.      * We don't want to increment blevel for every frame that times
  520.      * out, since that would lead to us backing off too fast when
  521.      * all the frame timers expired at around the same time.
  522.      */
  523.     cb->txmax = 0;
  524.     
  525.     for(seq = cb->ackxpected;
  526.          nr4between(cb->ackxpected, seq, cb->nextosend);
  527.          seq = (seq + 1) & NR4SEQMASK)
  528.         if(cb->txbufs[seq % cb->window].retries > cb->txmax)
  529.             cb->txmax = cb->txbufs[seq % cb->window].retries;
  530.  
  531.     /* This is kind of a hack.  This function is called under
  532.      * three different conditions:  either we are choked, in
  533.      * which case we return immediately, or we are not choked,
  534.      * in which case we proceed normally to keep the send
  535.      * window full, or we have seen the choke flag for the first
  536.      * time.  In the last case, gotchoke is true while cb->choked
  537.      * is false.  We want to process any acknowledgments of existing
  538.      * frames in the send window before we purge it, while at the
  539.      * same time we don't want to take anything else off the txq
  540.      * or send it out.  So, in the third case we listed, we return
  541.      * now since we've processed the ACK.
  542.      */
  543.     
  544.     if(gotchoke)
  545.         return;
  546.  
  547.     nr4output(cb);            /* yank stuff off txq and send it */
  548.  
  549.     /* At this point, either the send window is full, or
  550.      * nr4output() didn't find enough on the txq to fill it.
  551.      * If the window is not full, then the txq must be empty,
  552.      * and we'll make a tx upcall
  553.      */
  554.     if(cb->nbuffered < cb->window && cb->t_upcall != NULLVFP)
  555.         (*cb->t_upcall)(cb, (int16)((cb->window - cb->nbuffered) * Nr_iface->mtu));
  556.  
  557. }
  558.  
  559.  
  560. /* If the send window is open and there are frames on the txq,
  561.  * move as many as possible to the transmit buffers and send them.
  562.  * Return the number of frames sent.
  563.  */
  564. int
  565. nr4output(cb)
  566. struct nr4cb *cb;
  567. {
  568.     int numq, i;
  569.     struct mbuf *bp;
  570.     struct nr4txbuf *tp;
  571.  
  572.     /* Are we in the proper state? */
  573.     if(cb->state != NR4STCON || cb->choked)
  574.         return 0;        /* No sending if not connected */
  575.                     /* or if choked */
  576.         
  577.     /* See if the window is open */
  578.     if(cb->nbuffered >= cb->window)
  579.         return 0;
  580.  
  581.     numq = len_q(cb->txq);
  582.     
  583. #ifdef NR4DEBUG
  584.     tprintf("nr4output: %d packets on txq\n", numq);
  585. #endif
  586.     
  587.     for(i = 0; i < numq; i++){
  588.         bp = dequeue(&cb->txq);
  589. #ifdef NR4DEBUG
  590.         if(len_p(bp) > NR4MAXINFO){    /* should be checked higher up */
  591.             tputs("Upper layers queued too big a buffer\n");
  592.             continue;
  593.         }
  594. #endif
  595.         /* Set up and send buffer */
  596.         tp = &cb->txbufs[cb->nextosend % cb->window];
  597.         tp->retries = 0;
  598.         tp->data = bp;
  599.         nr4sbuf(cb, cb->nextosend);
  600.  
  601.         /* Update window and buffered count */
  602.         cb->nextosend = (cb->nextosend + 1) & NR4SEQMASK;
  603.         if(++cb->nbuffered >= cb->window)
  604.             break;
  605.     }
  606.     return i;
  607. }
  608.  
  609. void
  610. nr4state(cb, newstate)
  611. struct nr4cb *cb;
  612. int newstate;
  613. {
  614.     int i;
  615.     int oldstate = cb->state;
  616.  
  617.     cb->state = newstate;
  618.  
  619.     switch(cb->state){
  620.     case NR4STDPEND:
  621.         stop_timer(&cb->tchoke);
  622.  
  623.         /* When we request a disconnect, we lose the contents of
  624.          * our transmit queue and buffers, but we retain our ability
  625.          * to receive any packets in transit until a disconnect
  626.          * acknowledge arrives
  627.          */
  628.         free_q(&cb->txq);
  629.  
  630.         for(i = 0; i < cb->window; i++){
  631.             free_mbuf(cb->txbufs[i].data);
  632.             cb->txbufs[i].data = NULLBUF;
  633.             stop_timer(&cb->txbufs[i].tretry);
  634.         }
  635.  
  636.         /* Tidy up stats: roll the top window pointer back
  637.          * and reset nbuffered to reflect this.  Not really
  638.          * necessary, but leads to a bit more truth telling
  639.          * in the status displays.
  640.          */
  641.         cb->nextosend = cb->ackxpected;
  642.         cb->nbuffered = 0;
  643.         break;
  644.     case NR4STDISC:
  645.         stop_timer(&cb->tchoke);
  646.         stop_timer(&cb->tack);
  647.         stop_timer(&cb->tcd);
  648.         stop_timer(&cb->inactivity);
  649.  
  650.         /* We don't clear the rxq, since the state change upcall
  651.          * may pull something off of it at the last minute.
  652.          */
  653.         free_q(&cb->txq);
  654.  
  655.         /* The following loop will only be executed if the
  656.          * window was set, since when the control block is
  657.          * calloc'd the window field gets a 0 in it.  This
  658.          * protects us from dereferencing an unallocated
  659.          * window buffer pointer
  660.          */
  661.         for(i = 0; i < cb->window; i++){
  662.             free_mbuf(cb->rxbufs[i].data);
  663.             cb->rxbufs[i].data = NULLBUF;
  664.             free_mbuf(cb->txbufs[i].data);
  665.             cb->txbufs[i].data = NULLBUF;
  666.             stop_timer(&cb->txbufs[i].tretry);
  667.         }
  668.         break;
  669.     }
  670.  
  671.     if(oldstate != newstate && cb->s_upcall != NULLVFP)
  672.         (*cb->s_upcall)(cb, oldstate, newstate);
  673.  
  674.     /* We take responsibility for deleting the circuit
  675.      * descriptor.  Don't do this anywhere else!
  676.      */
  677.     if(newstate == NR4STDISC)
  678.         free_n4circ(cb);
  679. }
  680.  
  681. /* Process NAKs.  seq indicates the next frame expected by the
  682.  * NAK'ing station.
  683.  */
  684.  
  685. static void near
  686. nr4gotnak(cb, seq)
  687. struct nr4cb *cb;
  688. unsigned seq;
  689. {
  690.     if(nr4between(cb->ackxpected, seq, cb->nextosend))
  691.         nr4sbuf(cb, seq);
  692. }
  693.  
  694. /* This is called when we first get a CHOKE indication from the
  695.  * remote.  It purges the send window and sets the choke timer.
  696.  */
  697.  
  698. static void near
  699. nr4choke(cb)
  700. struct nr4cb *cb;
  701. {
  702.     unsigned seq;
  703.     struct nr4txbuf *t;
  704.     struct mbuf *bp, *q = cb->txq;
  705.  
  706.     /* We purge the send window, returning the buffers to the
  707.      * txq in the proper order.
  708.      */
  709.     for(seq = (cb->nextosend - 1) & NR4SEQMASK;
  710.          nr4between(cb->ackxpected, seq, cb->nextosend);
  711.          seq = (seq - 1) & NR4SEQMASK){
  712.  
  713.         t = &cb->txbufs[seq % cb->window];
  714.         stop_timer(&t->tretry);
  715.         bp = t->data;
  716.         t->data = NULLBUF;
  717.         enqueue(&bp, q);    /* prepend this packet to the queue */
  718.         q = bp;
  719.      }
  720.  
  721.     cb->nextosend = cb->ackxpected;    /* close the window */
  722.     cb->nbuffered = 0;        /* nothing in the window */
  723.     cb->txq = q;            /* Replace the txq with the one that has */
  724.                     /* the purged packets prepended */
  725.     cb->choked = 1;        /* Set the choked flag */
  726.  
  727.     start_timer(&cb->tchoke);
  728. }
  729.  
  730. #endif /* NETROM */
  731.